﻿namespace LaoLuo
{
    using System;
    using System.Collections.Generic;
    using System.Linq;

    /// <summary>
    /// A servant will be on duty every some time, and can do some work same type of duty-work when request is get
    /// </summary>
    /// <typeparam name="T"></typeparam>
    public class ServantSoleDuty<T> : IDisposable
    {
        /// <summary>
        /// timer for duty
        /// </summary>
        private readonly TimerWithAlarm _timer;

        /// <summary>
        /// action to do on duty
        /// </summary>
        private Action<T> _duty;

        /// <summary>
        /// init a <see cref="ServantSoleDuty&lt;T>"/>
        /// </summary>
        /// <param name="duty">action to do on duty</param>
        /// <param name="getWorkToDo">func to get some work</param>
        /// <param name="interval">duty interval</param>
        public ServantSoleDuty(Action<T> duty, Func<IEnumerable<T>> getWorkToDo, TimeSpan interval)
            : this(duty, getWorkToDo, interval.TotalMilliseconds)
        {
        }

        /// <summary>
        /// init a <see cref="ServantSoleDuty&lt;T>"/>
        /// </summary>
        /// <param name="duty">action to do on duty</param>
        /// <param name="getWorkToDo">func to get some work</param>
        /// <param name="interval">duty interval</param>
        public ServantSoleDuty(Action<T> duty, Func<IEnumerable<T>> getWorkToDo, double interval)
        {
            _duty = duty;
            _timer = new TimerWithAlarm(() => {
                foreach (var item in getWorkToDo())
                {
                    duty(item);
                }
            }, interval);
        }

        /// <summary>
        /// give some work to the servant
        /// </summary>
        /// <param name="work">works to do</param>
        public void Do(IEnumerable<Work<T>> work)
        {
            Worker.Do(_duty, work);
        }

        /// <summary>
        /// give some work to the servant
        /// </summary>
        /// <param name="work">works to do</param>
        public void Do(params Work<T>[] work)
        {
            Do(work.AsEnumerable());
        }

        /// <summary>
        /// dispose
        /// </summary>
        public void Dispose()
        {
            _timer.Stop();
            _timer.Dispose();
            _duty = null;
        }
    }
}
